<template>
  <el-table
    ref="tableRef"
    :data="tableData"
    :border="border"
    :stripe="stripe"
    :height="height"
    :max-height="maxHeight"
    :row-key="rowKey"
    :empty-text="emptyText"
    :highlight-current-row="highlightCurrentRow"
    @selection-change="handleSelectionChange"
  >
    <!-- 多选框列 -->
    <el-table-column
      v-if="showSelection"
      type="selection"
      width="55"
      :selectable="(row) => !row.isAddRow"
    />

    <!-- 动态列 -->
    <el-table-column
      v-for="column in columns"
      :key="column.prop"
      :prop="column.prop"
      :label="column.label"
      :width="column.width"
      :min-width="column.minWidth"
      :align="column.align || 'left'"
      :fixed="column.fixed"
    >
      <template #default="{ row, $index }">
        <template v-if="!row.isAddRow">
          <!-- 编辑状态 -->
          <template v-if="row.isEditing && column.editable !== false">
            <!-- 输入框 -->
            <el-input
              v-if="column.type === CellType.INPUT"
              v-model="row[column.prop]"
              size="small"
              :placeholder="column.placeholder || `请输入${column.label}`"
            />
            
            <!-- 数字输入框 -->
            <el-input-number
              v-else-if="column.type === CellType.INPUT_NUMBER"
              v-model="row[column.prop]"
              size="small"
              :min="column.min"
              :max="column.max"
              precision="2"
              :step="column.step || 1"
              :placeholder="column.placeholder || `请输入${column.label}`"
            />
            
            <!-- 日期选择器 -->
            <el-date-picker
              v-else-if="column.type === CellType.DATE_PICKER"
              v-model="row[column.prop]"
              type="date"
              size="small"  
              :placeholder="column.placeholder || `选择日期`"
              :format="column.format || 'YYYY-MM-DD'"
              :value-format="column.valueFormat || 'YYYY-MM-DD'"
            />
            
            <!-- 时间选择器 -->
            <el-time-picker
              v-else-if="column.type === CellType.TIME_PICKER"
              v-model="row[column.prop]"
              size="small"
              :placeholder="column.placeholder || `选择时间`"
              :format="column.format || 'HH:mm:ss'"
              :value-format="column.valueFormat || 'HH:mm:ss'"
            />
            
            <!-- 日期时间选择器 -->
            <el-date-picker
              v-else-if="column.type === CellType.DATETIME_PICKER"
              v-model="row[column.prop]"
              type="datetime"
              size="small"
              :placeholder="column.placeholder || `选择日期时间`"
              :format="column.format || 'YYYY-MM-DD HH:mm:ss'"
              :value-format="column.valueFormat || 'YYYY-MM-DD HH:mm:ss'"
            />
            
            <!-- 单选框 -->
            <el-radio-group
              v-else-if="column.type === CellType.RADIO"
              v-model="row[column.prop]"
              size="small"
            >
              <el-radio
                v-for="option in column.options"
                :key="option.value"
                :label="option.value"
                :disabled="option.disabled"
              >
                {{ option.label }}
              </el-radio>
            </el-radio-group>
            
            <!-- 多选框 -->
            <el-checkbox-group
              v-else-if="column.type === CellType.CHECKBOX"
              v-model="row[column.prop]"
              size="small"
            >
              <el-checkbox
                v-for="option in column.options"
                :key="option.value"
                :label="option.value"
                :disabled="option.disabled"
              >
                {{ option.label }}
              </el-checkbox>
            </el-checkbox-group>
            
            <!-- 下拉单选 -->
            <el-select
              v-else-if="column.type === CellType.SELECT"
              v-model="row[column.prop]"
              size="small"
              :placeholder="column.placeholder || `请选择${column.label}`"
            >
              <el-option
                v-for="option in column.options"
                :key="option.value"
                :label="option.label"
                :value="option.value"
                :disabled="option.disabled"
              />
            </el-select>
            
            <!-- 下拉多选 -->
            <el-select
              v-else-if="column.type === CellType.SELECT_MULTIPLE"
              v-model="row[column.prop]"
              size="small"
              multiple
              :placeholder="column.placeholder || `请选择${column.label}`"
            >
              <el-option
                v-for="option in column.options"
                :key="option.value"
                :label="option.label"
                :value="option.value"
                :disabled="option.disabled"
              />
            </el-select>
            
            <!-- 开关 -->
            <el-switch
              v-else-if="column.type === CellType.SWITCH"
              v-model="row[column.prop]"
              size="small"
            />
            
            <!-- 默认文本 -->
            <span v-else>{{ formatCellValue(row, column, $index) }}</span>
          </template>
          
          <!-- 非编辑状态 -->
          <span v-else>{{ formatCellValue(row, column, $index) }}</span>
        </template>
      </template>
    </el-table-column>

    <!-- 操作列 -->
    <el-table-column
      v-if="showOperation"
      label="操作"
      min-widthwidth="150"
      fixed="right"
    >
      <template #default="{ row, $index }">
        <template v-if="row.isAddRow">
          <el-button
            v-if="showAddRow"
            type="text"
            size="small"
            @click="handleAddNewRow"
          >
            + 添加行
          </el-button>
        </template>
        <template v-else-if="row.isEditing">
          <el-button type="text" size="small" @click="handleSaveRow(row, $index)">
            保存
          </el-button>
          <el-button type="text" size="small" @click="handleCancelEdit(row, $index)">
            取消
          </el-button>
        </template>
        <template v-else>
          <el-button type="text" size="small" @click="handleEditRow(row, $index)">
            编辑
          </el-button>
          <el-button type="text" size="small" @click="handleDeleteRow(row, $index)">
            删除
          </el-button>
        </template>
      </template>
    </el-table-column>
  </el-table>
</template>

<script setup lang="ts">
/**
 * IdooAddRowTable 可编辑表格组件
 * @author AI Assistant
 * @description 支持多种单元格类型、添加行、编辑、删除等功能的表格组件
 */
import { ref, computed, watch, nextTick } from 'vue'
import { ElMessage, ElMessageBox, ElTable } from 'element-plus'
import type {
  TableRow,
  ColumnConfig,
  IdooAddRowTableProps,
  IdooAddRowTableExpose
} from  './IdooAddRowTable.ts'
import { CellType } from  './IdooAddRowTable.ts'

// 定义组件props
const props = withDefaults(defineProps<IdooAddRowTableProps>(), {
  showOperation: true,
  showAddRow: true,
  showSelection: true,
  border: true,
  stripe: false,
  rowKey: '_id',
  emptyText: '暂无数据',
  highlightCurrentRow: false
})

// 定义组件emits
const emit = defineEmits<{
  dataChange: [data: TableRow[]]
  rowEdit: [row: TableRow, index: number]
  rowSave: [row: TableRow, index: number, callback?: (result: boolean | { success: boolean }) => void]
  rowDelete: [row: TableRow, index: number]
  selectionChange: [selection: TableRow[]]
}>()

// 表格引用
const tableRef = ref<InstanceType<typeof ElTable>>()

// 内部表格数据
const tableData = ref<TableRow[]>([])

// 已选择的行
const selectedRows = ref<TableRow[]>([])

// 新增的数据ID集合
const addedRowIds = ref<Set<string | number>>(new Set())

// 删除的数据
const deletedRows = ref<TableRow[]>([])

// 行ID计数器
let rowIdCounter = 1

/**
 * 生成唯一的行ID
 */
const generateRowId = (): string => {
  return `new_${Date.now()}_${rowIdCounter++}`
}

/**
 * 初始化表格数据
 */
const initTableData = () => {
  const data = props.data.map(row => ({
    ...row,
    _id: row._id || generateRowId()
  }))
  
  // 如果需要显示添加行按钮，在末尾添加特殊行
  if (props.showAddRow && props.showOperation) {
    data.push({ isAddRow: true, _id: 'add_row_button' })
  }
  
  tableData.value = data
}

// 监听props.data变化
watch(() => props.data, () => {
  initTableData()
}, { immediate: true, deep: true })

/**
 * 格式化单元格显示值
 */
const formatCellValue = (row: TableRow, column: ColumnConfig, index: number): string => {
  const value = row[column.prop]
  
  // 如果有自定义格式化函数
  if (column.formatter) {
    return column.formatter(row, column, value, index)
  }
  
  // 处理数组类型（多选）
  if (Array.isArray(value)) {
    if (column.type === CellType.CHECKBOX || column.type === CellType.SELECT_MULTIPLE) {
      const labels = value.map(v => {
        const option = column.options?.find(opt => opt.value === v)
        return option?.label || v
      })
      return labels.join(', ')
    }
    return value.join(', ')
  }
  
  // 处理布尔值
  if (typeof value === 'boolean') {
    return value ? '是' : '否'
  }
  
  // 处理选项类型
  if ((column.type === CellType.SELECT || column.type === CellType.RADIO) && column.options) {
    const option = column.options.find(opt => opt.value === value)
    return option?.label || value
  }
  
  return value?.toString() || ''
}

/**
 * 处理添加新行
 */
const handleAddNewRow = () => {
  const newRowId = generateRowId()
  const newRow: TableRow = {
    _id: newRowId,
    isEditing: true,
    isNew: true
  }
  
  // 初始化各列的默认值
  props.columns.forEach(column => {
    if (column.type === CellType.INPUT_NUMBER) {
      newRow[column.prop] = column.min || 0
    } else if (column.type === CellType.CHECKBOX || column.type === CellType.SELECT_MULTIPLE) {
      newRow[column.prop] = []
    } else if (column.type === CellType.SWITCH) {
      newRow[column.prop] = false
    } else {
      newRow[column.prop] = ''
    }
  })
  
  // 在添加行按钮之前插入新行
  const insertIndex = props.showAddRow ? tableData.value.length - 1 : tableData.value.length
  tableData.value.splice(insertIndex, 0, newRow)
  
  // 记录为新增数据
  addedRowIds.value.add(newRowId)
}

/**
 * 处理编辑行
 */
const handleEditRow = (row: TableRow, index: number) => {
  // 保存原始数据
  row.originalData = {}
  props.columns.forEach(column => {
    row.originalData[column.prop] = row[column.prop]
  })
  row.isEditing = true
  
  emit('rowEdit', row, index)
}

/**
 * 处理保存行
 */
const handleSaveRow = async (row: TableRow, index: number) => {
  // 验证必填字段
  for (const column of props.columns) {
    if (column.required && !row[column.prop]) {
      ElMessage.warning(`请填写${column.label}`)
      return
    }
    
    // 自定义验证
    if (column.validator) {
      const result = column.validator(row[column.prop], row)
      if (result !== true) {
        ElMessage.warning(typeof result === 'string' ? result : `${column.label}验证失败`)
        return
      }
    }
  }
  
  try {
    // 等待父组件的保存操作完成
    const saveResult = await new Promise((resolve) => {
      // 发出保存事件，并传递回调函数
      emit('rowSave', row, index, resolve)
    })
    
    // 根据保存结果决定是否退出编辑状态
    if (saveResult === true || (saveResult as any)?.success === true) {
      // 保存成功，退出编辑状态
      row.isEditing = false
      delete row.isNew
      delete row.originalData
      emit('dataChange', getActualData())
    }
    // 如果保存失败，保持编辑状态，不做任何操作
  } catch (error) {
    console.error('保存操作异常:', error)
    // 出现异常时保持编辑状态
  }
}

/**
 * 处理取消编辑
 */
const handleCancelEdit = (row: TableRow, index: number) => {
  if (row.isNew) {
    // 新增行直接删除
    tableData.value.splice(index, 1)
    addedRowIds.value.delete(row._id!)
  } else {
    // 恢复原始数据
    if (row.originalData) {
      Object.assign(row, row.originalData)
      delete row.originalData
    }
    row.isEditing = false
  }
}

/**
 * 处理删除行
 */
const handleDeleteRow = (row: TableRow, index: number) => {
  ElMessageBox.confirm('确定要删除这条数据吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    // 如果是新增的数据，从新增集合中移除
    if (addedRowIds.value.has(row._id!)) {
      addedRowIds.value.delete(row._id!)
    } else {
      // 否则记录到删除集合
      deletedRows.value.push({ ...row })
    }
    
    tableData.value.splice(index, 1)
    emit('rowDelete', row, index)
    emit('dataChange', getActualData())
    // ElMessage.success('删除成功')
  }).catch(() => {
    // 用户取消
  })
}

/**
 * 处理选择变化
 */
const handleSelectionChange = (selection: TableRow[]) => {
  selectedRows.value = selection
  emit('selectionChange', selection)
}

/**
 * 获取实际数据（排除添加行按钮）
 */
const getActualData = (): TableRow[] => {
  return tableData.value.filter(row => !row.isAddRow)
}

/**
 * 获取所有表格数据
 */
const getAllData = (): TableRow[] => {
  return getActualData()
}

/**
 * 获取新增的数据
 */
const getAddedData = (): TableRow[] => {
  return getActualData().filter(row => addedRowIds.value.has(row._id!))
}

/**
 * 获取删除的数据
 */
const getDeletedData = (): TableRow[] => {
  return [...deletedRows.value]
}

/**
 * 获取勾选的数据
 */
const getSelectedData = (): TableRow[] => {
  return [...selectedRows.value]
}

/**
 * 添加新行（外部调用）
 */
const addNewRow = () => {
  handleAddNewRow()
}

/**
 * 清空选择
 */
const clearSelection = () => {
  tableRef.value?.clearSelection()
  selectedRows.value = []
}

/**
 * 验证表格数据
 */
const validate = async (): Promise<boolean> => {
  const data = getActualData()
  
  for (const row of data) {
    for (const column of props.columns) {
      if (column.required && !row[column.prop]) {
        ElMessage.warning(`第${data.indexOf(row) + 1}行的${column.label}不能为空`)
        return false
      }
      
      if (column.validator) {
        const result = column.validator(row[column.prop], row)
        if (result !== true) {
          const message = typeof result === 'string' ? result : `第${data.indexOf(row) + 1}行的${column.label}验证失败`
          ElMessage.warning(message)
          return false
        }
      }
    }
  }
  
  return true
}

// 暴露组件方法
defineExpose<IdooAddRowTableExpose>({
  getAllData,
  getAddedData,
  getDeletedData,
  getSelectedData,
  addNewRow,
  clearSelection,
  validate
})
</script>

<style scoped>
/* 组件样式 */
:deep(.el-table) {
  font-size: 14px;
}

:deep(.el-table th) {
  background-color: #f5f7fa;
  color: #606266;
  font-weight: 600;
}

:deep(.el-button--text) {
  padding: 0 5px;
}

:deep(.el-input--small) {
  width: 100%;
}

:deep(.el-select--small) {
  width: 100%;
}

:deep(.el-date-editor--small) {
  width: 100%;
}
</style>
